package com.shenghua.service.impl;

import com.alibaba.fastjson.JSON;
import com.shenghua.dao.mapper.RolesMapper;
import com.shenghua.dao.mapper.UserMapper;
import com.shenghua.dao.mapperX.UserMapperX;
import com.shenghua.dao.model.Roles;
import com.shenghua.dao.model.RolesExample;
import com.shenghua.dao.model.User;
import com.shenghua.dao.model.UserExample;
import com.shenghua.dao.page.Page;
import com.shenghua.service.UserService;
import com.shenghua.utils.ListUtils;
import com.shenghua.utils.MD5Util;
import com.shenghua.utils.RedisUtils;
import com.shenghua.utils.StringUtils;
import com.shenghua.utils.beans.Constants;
import com.shenghua.utils.beans.Dto;
import com.shenghua.utils.beans.ErrorCode;
import com.shenghua.utils.constants.UserStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Administrator on 2018/12/23.
 */
@Service
public class UserServiceImpl implements UserService{
    Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserMapperX userMapperX;
    @Autowired
    private RolesMapper rolesMapper;
    @Resource
    private RedisUtils redisUtils;

    @Value(value = "${LoginRedisLock}")
    private boolean LoginRedisLock;//用户登录开启redis锁

    @Override
    public Dto<User> login(User user) {
        Dto<User> dto = new Dto<>();
        if(LoginRedisLock && redisUtils.exist(user.getLinkman())) {
            logger.debug("[UserServiceImpl] login 用户已经登录，不可重复登录！");
            dto.ReturnFail(new User(), ErrorCode.LOGIN_REPEAT);
            return dto;
        }
        String userPwd = user.getPwd();
        user.setPwd(StringUtils.handleSensitivePwd(user.getPwd()));
        logger.info("[UserServiceImpl] login 登录用户信息：" + JSON.toJSONString(user));

        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria();
        criteria.andLinkmanEqualTo(user.getLinkman());
        userExample.or(criteria);

        UserExample.Criteria criteria1 = userExample.createCriteria();
        criteria1.andPhoneEqualTo(user.getLinkman());
        userExample.or(criteria1);

        List<User> userList = userMapper.selectByExample(userExample);

        if(ListUtils.isNotEmpty(userList)) {//账号存在
            User user1 = userList.get(0);
            if(StringUtils.isBlank(user1.getStatus())) {
                logger.debug("[UserServiceImpl] login 账号状态未知！");
                dto.ReturnFail(new User(), ErrorCode.USER_UNKNOW_STATUS);
                return dto;
            } else if(UserStatus.STOPED.getVal().equalsIgnoreCase(user1.getStatus())){
                logger.debug("[UserServiceImpl] login 账号已停用！");
                dto.ReturnFail(new User(), ErrorCode.USER_STOPED);
                return dto;
            } else if(UserStatus.FORBIDDEN.getVal().equalsIgnoreCase(user1.getStatus())){
                logger.debug("[UserServiceImpl] login 账号已禁用！");
                dto.ReturnFail(new User(), ErrorCode.USER_FORBIDDEN);
                return dto;
            } else if(UserStatus.FROZEN.getVal().equalsIgnoreCase(user1.getStatus())){
                logger.debug("[UserServiceImpl] login 账号已冻结！");
                dto.ReturnFail(new User(), ErrorCode.USER_FROZEN);
                return dto;
            }

            // 判断密码是否正确
            if(null !=user1.getPwd() && !MD5Util.getMD5(userPwd).equals(user1.getPwd())){
                logger.debug("[UserServiceImpl] login 账号或密码不正确！");
                dto.ReturnFail(new User(), ErrorCode.LOGINNAME_OR_PWD_MISTAKE);
                return dto;
            }
            // 禁止多次登录
            if(LoginRedisLock && !redisUtils.lock(user1.getLinkman())) {
                logger.debug("[UserServiceImpl] login 账号加锁失败！");
                dto.ReturnFail(new User(), ErrorCode.LOGIN_LOCK_FAIL);
                return dto;
            }
            logger.info("[UserServiceImpl] login 登录成功！");
            user1.setLastLoginTime(new Date());
            user1.setLastLoginIp(user.getLastLoginIp());
            userMapper.updateByPrimaryKeySelective(user1);
            user1.setPwd(StringUtils.handleSensitivePwd(user.getPwd()));
            dto.ReturnSuccess(user1, ErrorCode.LOGIN_SUCCESS);
            logger.info("[UserServiceImpl] login 登录成功信息：" + JSON.toJSONString(dto));
            return dto;
        } else {
            logger.debug("[UserServiceImpl] login 用户名不存在！");
            dto.ReturnFail(new User(), ErrorCode.LOGINNAME_NOT_EXISTS);
            return dto;
        }
    }

    @Override
    public Dto<User> register(User user) {
        logger.info("[UserServiceImpl] register 参数：" + JSON.toJSONString(user));
        Dto<User> dto = new Dto<>();
        // 判断参数是否合格
        if(user == null || StringUtils.isBlank(user.getLinkman()) ||
                StringUtils.isBlank(user.getPwd())) {
            logger.info("[UserServiceImpl] register " + ErrorCode.AUTH_USER_MSG_NULL.getValue());
            dto.ReturnFail(new User(), ErrorCode.AUTH_USER_MSG_NULL);
            return dto;
        }
        String linkman = user.getLinkman();
        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria();
        criteria.andLinkmanEqualTo(linkman);
        UserExample.Criteria criteria1 = userExample.createCriteria();
        criteria1.andPhoneEqualTo(linkman);
        userExample.or(criteria);
        userExample.or(criteria1);
        // 判断是否已经被注册
        List<User> userList = userMapper.selectByExample(userExample);
        if(userList.size() > 0) {
            logger.info("[UserServiceImpl] register " + ErrorCode.AUTH_USER_ALREADY_EXISTS.getValue());
            dto.ReturnFail(new User(), ErrorCode.AUTH_USER_ALREADY_EXISTS);
            return dto;
        }
        // 加密密码
        user.setPwd(MD5Util.getMD5(user.getPwd()));
        user.setCreated(new Date());
        user.setStatus("1");
        int i = userMapper.insert(user);
        if(i <= 0) {
            logger.info("[UserServiceImpl] register " + ErrorCode.AUTH_USER_REGISTER_FAILED.getValue());
            dto.ReturnFail(new User(), ErrorCode.AUTH_USER_REGISTER_FAILED);
        } else {
            logger.info("[UserServiceImpl] register " + ErrorCode.AUTH_USER_REGISTER_SUCCESS.getValue());
            dto.ReturnSuccess(user, ErrorCode.AUTH_USER_REGISTER_SUCCESS);
        }
        return dto;
    }

    @Override
    public Dto<String> checkLinkman(String linkman) {
        Dto<String> dto = new Dto<>();
        if(StringUtils.isBlank(linkman)) {
            logger.info("[UserServiceImpl] checkLinkman 账号为空");
            dto.ReturnFail("", ErrorCode.AUTH_PARAMETER_ERROR);
        }

        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria();
        criteria.andLinkmanEqualTo(linkman);
        UserExample.Criteria criteria1 = userExample.createCriteria();
        criteria1.andPhoneEqualTo(linkman);
        userExample.or(criteria);
        userExample.or(criteria1);
        // 判断是否已经被注册
        List<User> userList = userMapper.selectByExample(userExample);
        if(userList.size() > 0) {
            logger.info("[UserServiceImpl] register " + ErrorCode.AUTH_USER_ALREADY_EXISTS.getValue());
            dto.ReturnFail("", ErrorCode.AUTH_USER_ALREADY_EXISTS);
            return dto;
        }
        logger.info("[UserServiceImpl] register " + ErrorCode.AUTH_USERNAME_USABLE.getValue());
        dto.ReturnSuccess("", ErrorCode.AUTH_USERNAME_USABLE);
        return dto;
    }

    @Override
    public Dto<Map<String, Object>> queryUserByPage(Map<String, Object> params, Page page) {
        Dto<Map<String,Object>> dto = new Dto<>();
        if(null == params || params.size() == 0) {
            logger.debug("[UserServiceImpl] queryUserByPage 参数为空");
            dto.ReturnFail(null, ErrorCode.USER_QUERY_IS_NULL);
            return dto;
        }
        if(null == page){
            logger.debug("[UserServiceImpl] queryUserByPage 分页信息为空");
            dto.ReturnFail(null, ErrorCode.PAGE_IS_NULL);
            return dto;
        }
        SimpleDateFormat sif = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 过滤查询条件
        Map<String,Object> map = new HashMap<>();
        if(null != params.get("linkman") && !"".equals(params.get("linkman"))){
            map.put("linkman",params.get("linkman"));
        }
        if(null != params.get("nickname") && !"".equals(params.get("nickname"))){
            map.put("nickname",params.get("nickname"));
        }
        if(null != params.get("departmentId") && !"".equals(params.get("departmentId"))){
            map.put("departmentId",params.get("departmentId"));
        }
        if(null != params.get("startTime") && !params.get("startTime").equals("") && null != params.get("endTime") && !params.get("endTime").equals("")){
            Date start = null;
            Date end = null;
            try {
                start = sif.parse(params.get("startTime").toString());
                end = sif.parse(params.get("endTime").toString());
            } catch (ParseException e) {
                logger.info("[UserServiceImpl] queryUserByPage 时间解析异常！");
                e.printStackTrace();
            }
            map.put("startTime", start);
            map.put("endTime", end);
        }
        map.put("begin", page.getBegin());
        map.put("end", page.getLength());
        int total = 0;
        List<User> list = new ArrayList<>();
        list = userMapperX.selectUserListByMap(map);
        total = userMapperX.countUserByMap(map);
        logger.info("***********************");
        logger.info("[UserServiceImpl] queryUserByPage 查询到的记录总数："+String.valueOf(total));
        logger.info("[UserServiceImpl] queryUserByPage 查询到的记录信息："+JSON.toJSONString(list));
        logger.info("***********************");
        // 返回数据
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("total",total);
        paramMap.put("rows", list);
        dto.ReturnSuccess(paramMap,ErrorCode.USER_Query_SUCCESS);
        return dto;
    }

    /**
     * 修改用户信息（角色等）
     * @param user
     * @return
     */
    @Override
    public Dto<User> editCurrentUser(User user) {
        logger.info("[UserServiceImpl] editCurrentUser user:{}", JSON.toJSONString(user));
        Dto<User> dto = new Dto<>();
        if(null == user || StringUtils.isBlank(user.getId())) {
            logger.info("[UserServiceImpl] editCurrentUser 参数不能为空");
            dto.ReturnFail(new User(),ErrorCode.PARAMETER_IS_NULL);
            return dto;
        }
        User user1 = userMapper.selectByPrimaryKey(user.getId());
        if(null == user1) {
            logger.info("[UserServiceImpl] editCurrentUser 用户不存在");
            dto.ReturnFail(new User(),ErrorCode.USER_NOT_EXISTS);
            return dto;
        }
        // 获取角色名称
        if(StringUtils.isNotBlank(user.getRoleId())) {
            Roles roles = rolesMapper.selectByPrimaryKey(user.getRoleId());
            if(null != roles) {
                if(StringUtils.isNotBlank(roles.getSign()) &&
                        Constants.ROLES_SUPER_ADMIN.equals(roles.getSign())) {
                    RolesExample example = new RolesExample();
                    RolesExample.Criteria criteria = example.createCriteria();
                    criteria.andSignEqualTo(Constants.ROLES_SUPER_ADMIN);
                    List<Roles> rolesList = rolesMapper.selectByExample(example);
                    if(ListUtils.isNotEmpty(rolesList)) {
                        logger.info("[UserServiceImpl] editCurrentUser 已经存在一个超级管理员用户：" + JSON.toJSONString(rolesList.get(0)));
                        dto.ReturnFail(new User(), ErrorCode.USER_SUPER_ADMIN_EDIT_FAIL);
                        return dto;
                    }
                }
                user.setRoleName(roles.getRoleName());
            }
        }
        user.setUpdated(new Date());

        int i = userMapper.updateByPrimaryKeySelective(user);
        if(!(i>0)) {
            dto.ReturnFail(new User(), ErrorCode.USER_EDIT_FAIL);
        } else {
            dto.ReturnSuccess(user, ErrorCode.USER_EDIT_SUCCESS);
        }
        return dto;
    }
}
